#!/usr/bin/env python3
# -*- coding: utf-8 -*-
##############################################
# @Author: DengLibin 榆霖
# @Date: Create in 2022-03-31 09:26:10
# @Description: kNN
##############################################
from cProfile import label
from email.policy import default

import matplotlib.pyplot as plt
import numpy as np
from paddle import norm
from pylab import mpl

from kNN import classify0


def to_int(label):
    if label == 'didntLike':
        return 1
    if label == 'smallDoses':
        return 2
    if label  == 'largeDoses':
        return 3

def file2matrix(filename):
    """把文本数据转换成为矩阵

    Args:
        filename (_type_): 文件

    Returns:
        _type_: _description_
    """
    with open(file = filename, mode='r') as f:
        lines = f.readlines()  
    num_of_lines = len(lines)
    # 创建矩阵
    return_mat = np.zeros((num_of_lines, 3))
    class_label_vector = []
    index = 0
    
    # 遍历行
    for line in lines:
        # 去掉首位空格和换行符
        line = line.strip()
        line_list = line.split('\t')
        # 前三列
        return_mat[index, :] = line_list[0:3]
        # 最后列
        class_label_vector.append(to_int(line_list[-1]))
        index += 1
    return return_mat, class_label_vector

def show_data():
    """散点图展示数据
    """
     # 设置显示中文
    mpl.rcParams["font.sans-serif"] = ["SimHei"]
    
    return_mat, class_label_vector = file2matrix('datingTestSet.txt')
    # 归一化
    return_mat, _ ,_ = auto_norm(return_mat)
    print(return_mat)
    plt.figure(figsize=(20, 8), dpi=100)
    # 散点图 用不同的大小和和颜色标注label
    #plt.scatter(return_mat[:, 1], return_mat[:, 2], 50.0 * np.array(class_label_vector), 20.0 * np.array(class_label_vector))
    type1_x = []
    type1_y = []
    type2_x = []
    type2_y = []
    type3_x = []
    type3_y = []
    for i in range(len(class_label_vector)):
        if class_label_vector[i] == 1:  # 不喜欢
            type1_x.append(return_mat[i][1])
            type1_y.append(return_mat[i][2])
            continue
        
        if class_label_vector[i] == 2:  # 魅力一般
            type2_x.append(return_mat[i][1])
            type2_y.append(return_mat[i][2])
            continue
            
        if class_label_vector[i] == 3:  # 极具魅力
            type3_x.append(return_mat[i][1])
            type3_y.append(return_mat[i][2])
            
        
    # 描述信息（x,y轴 标题）
    type1 = plt.scatter(type1_x, type1_y, s=20, c='red')
    type2 = plt.scatter(type2_x, type2_y, s=40, c='green')
    type3 = plt.scatter(type3_x, type3_y, s=50, c='blue')

    plt.xlabel('玩视频游戏所耗时间百分比')
    plt.ylabel('每年消费的冰淇淋公升数')
    plt.legend((type1, type2, type3), (u'不喜欢', u'魅力一般', u'极具魅力'), loc=1)
    plt.show()
    
    
def auto_norm(data_set):
    """归一化
    公式:
    new_value = (old_valud -min)/(max-min)
    Args:
        data_set (_type_): _description_
    """
    # 每列最小值
    min_value = data_set.min(0)
    # 每列最大值
    max_value = data_set.max(0)
    # 每列最大值和最小值之差
    ranges = max_value - min_value
    
    # 行数
    line_num = data_set.shape[0]
    # np.tile 平铺（line_num行）
    norm_data_set = data_set - np.tile(min_value, (line_num, 1))
    norm_data_set = norm_data_set / np.tile(ranges, (line_num, 1))
    return norm_data_set, ranges, min_value
    
def dating_class_test():
    """错误率测试
    """
    # 10%的数据作为测试数据
    ho_ratio = 0.10
    return_mat, class_label_vector = file2matrix('datingTestSet.txt')
    # 归一化
    norm_mat, ranges, min_valus = auto_norm(return_mat)
    # 行数
    m = norm_mat.shape[0]
    # 测试数据行数
    test_num = int(m * ho_ratio)
    error_count = 0
    for i in range(test_num):
        # 使用kNN算法计算当前行数据所属类别
        classifyer_result = classify0(norm_mat[i, :], norm_mat[test_num:, :], class_label_vector[test_num:], 3)
        print("classifyer_result is %d, the real label is %d" % (classifyer_result, class_label_vector[i]))
        if(classifyer_result != class_label_vector[i]):
            error_count += 1
    print('the total error rate is:%f' % (error_count/test_num))        


def classify_person():
    """约会预测函数
    """
    result_list = ['not at all', 'in small doses', 'in large doses']
    ff_miles = float(input('每年飞行里程数:'))
    persent_tats = float(input('玩游戏时间百分比:'))
    ice_cream = float(input('每年消费的冰淇淋公升数:'))
    
    dating_data_mat, dating_labels = file2matrix('datingTestSet.txt')
     # 归一化
    norm_mat, ranges, min_valus = auto_norm(dating_data_mat)
    inx = np.array([ff_miles, persent_tats, ice_cream])
    # 归一化
    norm_inx = (inx - min_valus)/ranges
    # print(norm_inx)
    # 预测结果
    classify_result = classify0(norm_inx, norm_mat, dating_labels, 3)
    
    print("You will probably like this person:%s" % result_list[classify_result - 1])
    
if __name__ == '__main__':
    # show_data()
    # dating_class_test()
    classify_person()
